package com.ruoyi.business.modbus.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.business.modbus.domain.ModbusTcpMasterDevice;
import com.ruoyi.business.modbus.domain.ModbusReadRequest;
import com.ruoyi.business.modbus.domain.ModbusReadResponse;
import com.ruoyi.business.modbus.domain.ModbusWriteResponse;
import com.ruoyi.business.modbus.service.IModbusCoreService;

/**
 * Modbus TCP控制器
 * 
 * @author ruoyi
 * @date 2024-01-01
 */
@RestController
@RequestMapping("/business/modbus/tcp")
public class ModbusTCPController extends BaseController
{
    @Autowired
    @Qualifier("modbus4jTcpService")
    private IModbusCoreService modbusTcpService;

    /**
     * 测试TCP设备连接
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:test')")
    @PostMapping("/testConnection")
    public AjaxResult testConnection(@RequestBody Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = createModbusTcpMasterDeviceFromParams(params);
        int slaveAddress = getIntParam(params, "slaveAddress", 1);
        
        ModbusReadResponse<Boolean> response = modbusTcpService.testConnection(modbusMasterEntity, slaveAddress);
        if (response.isSuccess()) {
            return AjaxResult.success(response.getMessage(), response.getData().get(0));
        } else {
            return AjaxResult.error(response.getMessage());
        }
    }

    /**
     * 读取保持寄存器
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:read')")
    @PostMapping("/readHoldingRegisters")
    public AjaxResult readHoldingRegisters(@RequestBody Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = createModbusTcpMasterDeviceFromParams(params);
        int slaveAddress = getIntParam(params, "slaveAddress", 1);
        int startAddress = getIntParam(params, "startAddress", 0);
        int quantity = getIntParam(params, "quantity", 1);
        
        ModbusReadResponse<Integer> response = modbusTcpService.readHoldingRegisters(modbusMasterEntity, slaveAddress, startAddress, quantity);
        if (response.isSuccess()) {
            return AjaxResult.success(response.getMessage(), response.getData());
        } else {
            return AjaxResult.error(response.getMessage());
        }
    }

    /**
     * 读取输入寄存器
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:read')")
    @PostMapping("/readInputRegisters")
    public AjaxResult readInputRegisters(@RequestBody Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = createModbusTcpMasterDeviceFromParams(params);
        int slaveAddress = getIntParam(params, "slaveAddress", 1);
        int startAddress = getIntParam(params, "startAddress", 0);
        int quantity = getIntParam(params, "quantity", 1);
        
        ModbusReadResponse<Integer> response = modbusTcpService.readInputRegisters(modbusMasterEntity, slaveAddress, startAddress, quantity);
        if (response.isSuccess()) {
            return AjaxResult.success(response.getMessage(), response.getData());
        } else {
            return AjaxResult.error(response.getMessage());
        }
    }

    /**
     * 读取线圈
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:read')")
    @PostMapping("/readCoils")
    public AjaxResult readCoils(@RequestBody Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = createModbusTcpMasterDeviceFromParams(params);
        int slaveAddress = getIntParam(params, "slaveAddress", 1);
        int startAddress = getIntParam(params, "startAddress", 0);
        int quantity = getIntParam(params, "quantity", 1);
        
        ModbusReadResponse<Boolean> response = modbusTcpService.readCoils(modbusMasterEntity, slaveAddress, startAddress, quantity);
        if (response.isSuccess()) {
            return AjaxResult.success(response.getMessage(), response.getData());
        } else {
            return AjaxResult.error(response.getMessage());
        }
    }

    /**
     * 读取离散输入
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:read')")
    @PostMapping("/readDiscreteInputs")
    public AjaxResult readDiscreteInputs(@RequestBody Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = createModbusTcpMasterDeviceFromParams(params);
        int slaveAddress = getIntParam(params, "slaveAddress", 1);
        int startAddress = getIntParam(params, "startAddress", 0);
        int quantity = getIntParam(params, "quantity", 1);
        
        ModbusReadResponse<Boolean> response = modbusTcpService.readDiscreteInputs(modbusMasterEntity, slaveAddress, startAddress, quantity);
        if (response.isSuccess()) {
            return AjaxResult.success(response.getMessage(), response.getData());
        } else {
            return AjaxResult.error(response.getMessage());
        }
    }

    /**
     * 写入单个线圈
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:write')")
    @PostMapping("/writeSingleCoil")
    public AjaxResult writeSingleCoil(@RequestBody Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = createModbusTcpMasterDeviceFromParams(params);
        int slaveAddress = getIntParam(params, "slaveAddress", 1);
        int address = getIntParam(params, "startAddress", 0);
        boolean value = getBooleanParam(params, "value", false);
        boolean verify = getBooleanParam(params, "verify", false);
        
        ModbusWriteResponse response = modbusTcpService.writeSingleCoil(modbusMasterEntity, slaveAddress, address, value, verify);
        if (response.isSuccess()) {
            return AjaxResult.success(response.getMessage());
        } else {
            return AjaxResult.error(response.getMessage());
        }
    }

    /**
     * 写入单个寄存器
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:write')")
    @PostMapping("/writeSingleRegister")
    public AjaxResult writeSingleRegister(@RequestBody Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = createModbusTcpMasterDeviceFromParams(params);
        int slaveAddress = getIntParam(params, "slaveAddress", 1);
        int address = getIntParam(params, "startAddress", 0);
        int value = getIntParam(params, "value", 0);
        boolean verify = getBooleanParam(params, "verify", false);
        
        ModbusWriteResponse response = modbusTcpService.writeSingleRegister(modbusMasterEntity, slaveAddress, address, value, verify);
        if (response.isSuccess()) {
            return AjaxResult.success(response.getMessage());
        } else {
            return AjaxResult.error(response.getMessage());
        }
    }


    /**
     * 获取连接状态
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:query')")
    @PostMapping("/connectionStatus")
    public AjaxResult getConnectionStatus(@RequestBody Map<String, Object> params)
    {
        String deviceSN = params.get("deviceSN").toString();
        boolean isConnected = modbusTcpService.getConnectionStatus(deviceSN);
        String message = isConnected ? "连接正常" : "连接不存在或已断开";
        return AjaxResult.success(message, isConnected);
    }

    /**
     * 获取设备统计信息
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:query')")
    @PostMapping("/deviceStatistics")
    public AjaxResult getDeviceStatistics(@RequestBody ModbusTcpMasterDevice modbusMasterEntity)
    {
        Map<String, Object> stats = modbusTcpService.getDeviceStatistics(modbusMasterEntity);
        return AjaxResult.success("获取设备统计信息成功", stats);
    }

    /**
     * 获取连接池统计信息
     */
    @PreAuthorize("@ss.hasPermi('business:modbus:tcp:query')")
    @GetMapping("/connectionPoolStatistics")
    public AjaxResult getConnectionPoolStatistics()
    {
        Map<String, Object> stats = modbusTcpService.getConnectionPoolStatistics();
        return AjaxResult.success("获取连接池统计信息成功", stats);
    }

    /**
     * 获取实现信息
     */
    @GetMapping("/implementationInfo")
    public AjaxResult getImplementationInfo()
    {
        Map<String, Object> info = modbusTcpService.getImplementationInfo();
        return AjaxResult.success("获取实现信息成功", info);
    }

    /**
     * 创建TCP设备示例
     */
    @GetMapping("/createTcpDeviceExample")
    public AjaxResult createTcpDeviceExample()
    {
        ModbusTcpMasterDevice modbusMasterEntity = ModbusTcpMasterDevice.create(
            "tcp_device_001", 
            "TCP设备示例", 
            "192.168.1.100", 
            502
        );
        return AjaxResult.success("创建示例设备", modbusMasterEntity);
    }

    /**
     * 从参数创建ModbusTcpMasterDevice
     */
    private ModbusTcpMasterDevice createModbusTcpMasterDeviceFromParams(Map<String, Object> params)
    {
        ModbusTcpMasterDevice modbusMasterEntity = new ModbusTcpMasterDevice();
        String sn = params.get("deviceSN").toString();
        modbusMasterEntity.setDeviceSN(sn);
        modbusMasterEntity.setDeviceName(params.get("deviceName").toString());
        modbusMasterEntity.setIpAddress(params.get("ipAddress").toString());
        modbusMasterEntity.setPort(getIntParam(params, "port", 502));
        
        if (params.containsKey("encapsulated")) {
            modbusMasterEntity.setEncapsulated(Boolean.parseBoolean(params.get("encapsulated").toString()));
        }
        if (params.containsKey("timeout")) {
            modbusMasterEntity.setTimeout(getIntParam(params, "timeout", 1000));
        }
        if (params.containsKey("retries")) {
            modbusMasterEntity.setRetries(getIntParam(params, "retries", 3));
        }
        
        return modbusMasterEntity;
    }

    /**
     * 从数据创建读取请求列表
     */
    private List<ModbusReadRequest> createReadRequestsFromData(List<Map<String, Object>> requestsData, int slaveAddress)
    {
        List<ModbusReadRequest> requests = new ArrayList<>();
        
        for (Map<String, Object> requestData : requestsData) {
            String requestId = requestData.get("requestId").toString();
            String functionCode = requestData.get("functionCode").toString();
            int startAddress = getIntParam(requestData, "startAddress", 0);
            int quantity = getIntParam(requestData, "quantity", 1);
            
            ModbusReadRequest request = new ModbusReadRequest(requestId, functionCode, slaveAddress, startAddress, quantity);
            
            if (requestData.containsKey("dataType")) {
                request.setDataType(getIntParam(requestData, "dataType", 0));
            }
            if (requestData.containsKey("description")) {
                request.setDescription(requestData.get("description").toString());
            }
            
            requests.add(request);
        }
        
        return requests;
    }

    /**
     * 获取整数参数，带默认值
     */
    private int getIntParam(Map<String, Object> params, String key, int defaultValue) {
        Object value = params.get(key);
        return value != null ? Integer.parseInt(value.toString()) : defaultValue;
    }

    /**
     * 获取布尔参数，带默认值
     */
    private boolean getBooleanParam(Map<String, Object> params, String key, boolean defaultValue) {
        Object value = params.get(key);
        return value != null ? Boolean.parseBoolean(value.toString()) : defaultValue;
    }
}
